package com.android.hdhe.uhf.reader;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import android.util.Log;

import com.android.hdhe.uhf.consts.Constants;
import com.android.hdhe.uhf.readerInterface.CommendManager;

public class SendCommendManager implements CommendManager{

	private InputStream in;
	private OutputStream out;
	
	public SendCommendManager(){}
	public SendCommendManager(InputStream in, OutputStream out){
		this.in = in ;
		this.out = out;
	}
	
//	public SendCommendManager(int serialPort, int baud, int flag ){
//		
//	}
	/////////////////////////系统设置函数//////////////////////////////////////////

	//设置波特率
	public boolean setBaudrate() {
		boolean flag = false;
		byte[] cmd = new byte[6];
		cmd[0] = Constants.HEAD;
		cmd[1] = (byte) (0x04);//len
		cmd[2] = (byte) (0xFF);//address
		cmd[3] = Constants.CMD_SET_BAUD;//cmd
		cmd[4] = (byte) (0x04);//04为波特率115200,03为38400
		cmd[5] = checkSum(cmd, cmd.length - 1);
		sendToReader(cmd);
		//接收返回数据
		byte[] recv = this.read();
		if(recv != null){
//			Log.i("set Baudrate", Tools.Bytes2HexString(recv, recv.length));
			if(isRecvData(recv) == 0) {
				if(Integer.valueOf(recv[3]) == Constants.CMD_SET_BAUD && Integer.valueOf(recv[4]) == Constants.CMD_SUCCESS) {
					flag = true;
				}
			}
		}else{
			Log.i("readFrom6C", "指令超时");
		}
		return flag;
	}

	//获取硬件版本
	public byte[] getFirmware() {
		byte[] cmd = new byte[5];
		cmd[0] = Constants.HEAD;
		cmd[1] = (byte) (0x03);
		cmd[2] = Constants.ADDR;
		cmd[3] = Constants.CMD_GET_FIRMWARE_VERSION;
		cmd[4] = checkSum(cmd, cmd.length - 1);
		sendToReader(cmd);
		byte[] recv = this.read();
		if(recv != null){
			System.out.println(new String(recv));
		}
		return recv;
		//
	}
	
	public byte[] getFrequency(){
		byte[] cmd = {(byte)0xA0 ,(byte)0x03 ,(byte)0x01 ,(byte)0x79 ,(byte)0xE3};
		sendToReader(cmd);
		byte[] recv = this.read();
		if(recv != null){
			System.out.println(Tools.Bytes2HexString(recv, recv.length));
		}
		return null;
	}
	
	/**
	 * 
	 * @param startFrequency 起始频点
	 * @param freqSpace 频点间隔
	 * @param freqQuality 频点数量
	 * @return
	 */
	public int setFrequency(int startFrequency, int freqSpace, int freqQuality){
		byte[] cmd = new byte[11];
		cmd[0] = Constants.HEAD;
		cmd[1] = 0x09;
		cmd[2] = Constants.ADDR;
		cmd[3] = 0x78; //自定义设置频点
		cmd[4] = 0x04;
		cmd[5] = (byte) (freqSpace/10);
		cmd[6] = (byte) freqQuality;
		cmd[7] = (byte) ((0xff0000&startFrequency)>>16);
		cmd[8] = (byte) ((0xff00&startFrequency)>>8);
		cmd[9] = (byte) (0xff&startFrequency);
		cmd[10] = checkSum(cmd, cmd.length - 1);
		System.out.println(Tools.Bytes2HexString(cmd, cmd.length));
		sendToReader(cmd);
		byte[] recv = this.read();
		if(recv != null){
			System.out.println(Tools.Bytes2HexString(recv, recv.length));
		}
		return 0;
	}
	
	//设置工作天线
	public void setWorkAntenna() {
		byte[] cmd = new byte[6];
		cmd[0] = Constants.HEAD;
		cmd[1] = (byte) (0x04);
		cmd[2] = Constants.ADDR;
		cmd[3] = Constants.CMD_SET_WORK_ANTENNA;
		cmd[4] = (byte) (0x00);//00为天线1，01为天线2，02为天线3，03为天线4，默认为天线1
		cmd[5] = checkSum(cmd, cmd.length - 1);
		sendToReader(cmd);
		
	}
	//读取输出功率
//	public byte[] getOutputPower(){
//		
//		return null;
//	}
	//设置输入输出功率
	public boolean setOutputPower(int value){
		byte[] cmd = new byte[6];
		cmd[0] = Constants.HEAD;;
		cmd[1] = (byte) (0x04);
		cmd[2] = Constants.ADDR;
		cmd[3] = (byte) (0x76);
		cmd[4] = (byte) value;
		cmd[5] = checkSum(cmd, cmd.length - 1);
//		Log.i("setOutputPower*****", Tools.Bytes2HexString(cmd, cmd.length));
		sendToReader(cmd);
		this.read();
		return true;
	}
	///////////////////////////////////ISO18000-6C///////////////////////////////////////
	//实时盘存
	public List<byte[]> inventoryRealTime() {
		List<byte[]> epcList = new ArrayList<byte[]>();
		byte[] cmd = new byte[6];
		cmd[0] = Constants.HEAD;
		cmd[1] = (byte) (0x04);
		cmd[2] = Constants.ADDR;//adress
		cmd[3] = Constants.CMD_6C_REAL_TIME_INVENTORY;
		cmd[4] = (byte) (0x01);
		cmd[5] = checkSum(cmd, cmd.length - 1);
		sendToReader(cmd);
		Log.i("", "send inventory real time***");
		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//接收返回数据
		byte[] recv = this.read();
		if(recv != null){
		int length = recv.length;
		List<byte[]> srcData = new ArrayList<byte[]>();
		int start = 0;
		while(length > 0){
			//判断包头
			if(recv[start] != Constants.HEAD){
				break;
			}else{
				int dataLen = (recv[start + 1]&(0xFF));
				byte[] data = new byte[dataLen + 2];
				if(data.length > 12 && data.length <= length){
					System.arraycopy(recv, start, data, 0, data.length);
//					Log.i("data *******", Tools.Bytes2HexString(data, data.length));
					byte []epc = new byte[data.length - 9];
					System.arraycopy(data, 7, epc, 0, data.length - 9);
//					System.out.println(Tools.Bytes2HexString(epc, epc.length));
					epcList.add(epc);
				}
				start += data.length;
				length -= data.length;

			}
		}
		
		}else{
			Log.i("realTimeInventory", "指令超时");
		}
		return epcList;
	}
	//选定标签
	public void selectEPC(byte[] epc) {
		int epcLen = epc.length;
		byte[] cmd = new byte[7 + epcLen];
		cmd[0] = Constants.HEAD;
		cmd[1] = (byte) (0x11);
		cmd[2] = Constants.ADDR;//adress
		cmd[3] = Constants.CMD_6C_SET_ACCESS_EPC_MATCH;
		cmd[4] = (byte) (0x00);
		cmd[5] = (byte) (0x0C);//EPC长度
		System.arraycopy(epc, 0, cmd, 6, epcLen);//6-18为EPC
		cmd[6 + epcLen] = checkSum(cmd, cmd.length - 1);
//		Log.i("Select epc****", Tools.Bytes2HexString(cmd, cmd.length));
		//发送指令
		sendToReader(cmd);
		//接收返回数据
		byte[] recv = this.read();
		if(recv != null){
//			Log.i("", Tools.Bytes2HexString(recv, recv.length));
		}else{
			Log.i("selectEPC", "指令超时");
		}
	}
	
	/*
	 * 读数据
	 * int memBank数据区
	 * int startAddr数据区起始地址（以字为单位）1字=2字节
	 * int length要读取的数据长度(以字为单位)
	 * 返回的byte[] 为  EPC + 读取的数据
	 */
	public byte[] readFrom6C(int memBank, int startAddr, int length) {
		byte[] data = null;
		byte[] cmd = new byte[8];
		cmd[0] = Constants.HEAD;
		cmd[1] = (byte) (0x06);
		cmd[2] = Constants.ADDR;//address
		cmd[3] = Constants.CMD_6C_READ;
		cmd[4] = (byte) memBank;
		cmd[5] = (byte) startAddr;
		cmd[6] = (byte) length;
		cmd[7] = checkSum(cmd, cmd.length - 1);
		//发送指令
		sendToReader(cmd);
//		Log.i("READ DATA*****", Tools.Bytes2HexString(cmd, cmd.length));
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		byte[] recv = this.read();
		if(recv != null){
//			Log.i("read data", Tools.Bytes2HexString(recv, recv.length));
			int len = recv.length;
			//判断数据包头
			if(recv[0] != Constants.HEAD){
				return data;
			}
			byte check = checkSum(recv, len - 1);
			//校验和
			if(check != recv[len - 1]){
			    Log.i("read data ", "checksum error");
				return data;
			}
			//操作失败
			if(len == 6){
				Log.i("read data ", "read fail!!");
				return data;
			}
			//操作成功
			//成功操作的标签总数
			int tagCount = (recv[4]&(0xFF))*256 + (recv[5]&(0xFF));
			//有效数据长度
			int dataLen = recv[6]&(0xFF);
			//读取的数据长度
			int readLen = recv[len - 4];
			
			int epcLen = dataLen - readLen - 4;
			if(dataLen <= readLen || dataLen < epcLen || epcLen < 0){
				return data;
			}
			data = new byte[readLen + epcLen];
			System.arraycopy(recv, 9, data, 0, epcLen);
			System.arraycopy(recv, 11 + epcLen, data, epcLen, readLen);
			
		}else{
			Log.i("read data ", "指令超时");
		}
	return data;	
	}
	
	
	
	/**
	 * 通过密码读数据
	 * @param memBank
	 * @param startAddr
	 * @param length
	 * @param password
	 * @return
	 */
	public byte[] readFrom6C(int memBank, int startAddr, int length, byte[] password) {
		byte[] data = null;
		byte[] cmd = new byte[12];
		cmd[0] = Constants.HEAD;
		cmd[1] = (byte) (0x0A);
		cmd[2] = Constants.ADDR;//address
		cmd[3] = Constants.CMD_6C_READ;
		cmd[4] = (byte) memBank;
		cmd[5] = (byte) startAddr;
		cmd[6] = (byte) length;
		if(password.length != 4 ){
			Log.e("readFrom6C", "password error");
			return null;
		}
//		System.arraycopy(cmd, 7, password, 0, 4);
		cmd[7] = password[0];
		cmd[8] = password[1];
		cmd[9] = password[2];
		cmd[10] = password[3];
		cmd[11] = checkSum(cmd, cmd.length - 1);
		//发送指令
		sendToReader(cmd);
//		Log.i("READ DATA*****", Tools.Bytes2HexString(cmd, cmd.length));
		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		byte[] recv = this.read();
		if(recv != null){
//			Log.i("read data", Tools.Bytes2HexString(recv, recv.length));
			int len = recv.length;
			//判断数据包头
			if(recv[0] != Constants.HEAD){
				return data;
			}
			byte check = checkSum(recv, len - 1);
			//校验和
			if(check != recv[len - 1]){
			    Log.i("read data ", "checksum error");
				return data;
			}
			//操作失败
			if(len == 6){
				Log.i("read data ", "read fail!!");
				return data;
			}
			//操作成功
			//成功操作的标签总数
			int tagCount = (recv[4]&(0xFF))*256 + (recv[5]&(0xFF));
			//有效数据长度
			int dataLen = recv[6]&(0xFF);
			//读取的数据长度
			int readLen = recv[len - 4];
			
			int epcLen = dataLen - readLen - 4;
			if(dataLen <= readLen || dataLen < epcLen || epcLen < 0){
				return data;
			}
			if(recv.length < (epcLen+9)){
				return data;
			}
			data = new byte[readLen + epcLen];
			
			System.arraycopy(recv, 9, data, 0, epcLen);
			System.arraycopy(recv, 11 + epcLen, data, epcLen, readLen);
			
		}else{
			Log.i("read data ", "指令超时");
		}
	return data;	
	}
	
    /*
     * 写数据
     * byte[] password 访问密码
     * int memBank 数据区
     * int wordAdd 起始地址（以WORD为单位）
     * int wordCnt 写入数据的长度
     * byte[] data 写入数据
     * 返回 boolean，true写入数据正确，false写入数据失败
     */
	public boolean writeTo6C(byte[] password, int memBank, int wordAdd, int dataLen, byte[] data) {
		boolean writeFlag = false;
		dataLen = dataLen/2;
		int cmdLen = 12 + dataLen*2;
		byte[] cmd = new byte[cmdLen];
		cmd[0] = Constants.HEAD;
		cmd[1] = (byte) (cmdLen - 2);
		cmd[2] = Constants.ADDR;
		cmd[3] = Constants.CMD_6C_WRITE;
		System.arraycopy(password, 0, cmd, 4, password.length);
		cmd[8] = (byte) memBank;
		cmd[9] = (byte) wordAdd;
		cmd[10] = (byte) dataLen;
		System.arraycopy(data, 0, cmd, 11, data.length);
		cmd[11 + data.length] = checkSum(cmd, 11 + data.length);
		sendToReader(cmd);
//		Log.i("write DATA*****", Tools.Bytes2HexString(cmd, cmd.length));
		try {
			Thread.sleep(150);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		byte[] recv = this.read();
		if(recv != null){
//			Log.i("write data======", Tools.Bytes2HexString(recv, recv.length));
			int recvLength = recv.length;
			//操作失败
			if(recvLength == 6){
				return writeFlag;
			}
			if(isRecvData(recv) == 0){
				writeFlag = true;
			}
		}else{
			Log.i("write data", "指令超时");
			try {
				Thread.sleep(1500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			this.read();
		}
		
		return writeFlag;
	}
	
	/**
	 * 
	 * @param password
	 * @param memBank
	 * @param lockType
	 * @return
	 */
	public boolean lock6C(byte[] password, int memBank, int lockType){
		boolean lockFlag = false;
		byte [] cmd = new byte[11];
		cmd[0] = Constants.HEAD;
		cmd[1] = (byte) 0x09;
		cmd[2] = Constants.ADDR;
		cmd[3] = Constants.CMD_6C_LOCK;
		System.arraycopy(password, 0, cmd, 4, password.length);
		cmd[8] = (byte) memBank;
		cmd[9] = (byte) lockType;
		cmd[10] = checkSum(cmd, cmd.length - 1);
//		Log.i("SendCommendManager","Lock" + Tools.Bytes2HexString(cmd, cmd.length));
		//发送指令
		sendToReader(cmd);
		//接收返回数据
		byte[] recv = this.read();
		if(recv != null){
//			Log.i("Lock..6c", Tools.Bytes2HexString(recv, recv.length));
			//操作失败
			if(recv.length == 6){
				return lockFlag;
			}
			if(isRecvData(recv) == 0){
				lockFlag = true;
			}
		}else{
			Log.i("Lock..6c", "超时");
		}
		return lockFlag;
		
	}
	/**
	 *@return void
	 *@Method Description:销毁标签
	 *@Autor Jimmy
	 *@Date 2014-1-18
	 */
	public boolean kill6C(byte[]password){
		boolean killFlag = false;
		byte[] cmd = new byte[9];
		cmd[0] = Constants.HEAD;
		cmd[1] = (byte) 0x07;
		cmd[2] = (byte) 0xFF;
		cmd[3] = Constants.CMD_6C_KILL;
		System.arraycopy(password, 0, cmd, 4, password.length);
		cmd[8] = checkSum(cmd, cmd.length - 1);
		
//		Log.i("Kill ***", Tools.Bytes2HexString(cmd, cmd.length));
		byte[] recv = this.read();
		if(recv != null){
//			Log.i("Kill ***", Tools.Bytes2HexString(recv, recv.length));
			if(recv.length == 6){
				return killFlag;
			}
			if(isRecvData(recv) == 0){
				killFlag = true;
			}
		}else{
			Log.i("Kill ***", "超时");
		}
		return killFlag;
	}
	
	///////////////////////////ISO18000-6B///////////////////////////////////////
	public void inventory6B(){
		byte[] cmd = {(byte) 0xA0, (byte) 0x03, (byte) 0x01, Constants.CMD_ISO18000_6B_INVENTORY, 0x00};
		
	}
	
	//接收缓存区的数据
	private  byte[] read(){
		int count = 0;
		int index = 0;
		int allCount = 0; 
		byte [] resp = null;
		try {
			while(count < 3){
				  count = this.in.available();
				  if(index > 50){
				    return null;//超时
				 }else{
					index++;
					try{
					  Thread.sleep(10);
					  }catch(InterruptedException e){
					   e.printStackTrace();
					 }
					}
				}
				Thread.sleep(50);
				allCount = this.in.available();
				resp = new byte[allCount];
				Log.i("read allCount****", allCount +"");
				int mcount = 0;
				while(count != 0){
				  byte[] bytes = new byte[2];
				  this.in.read(bytes);
				  int length = bytes[1];
				  count = 0; 
//				  while(count < length){
				    count = this.in.available();
				    Log.i("read count", count +"");
//				   }
				  byte[] data = new byte[length];
				  
				  int dataSize = this.in.read(data);
//				  Log.i("DATA SIZE", dataSize + "  data size  " + Tools.Bytes2HexString(data, dataSize));
				  System.arraycopy(bytes, 0, resp, mcount, 2);
				  System.arraycopy(data, 0, resp, mcount + 2, length);
				  mcount = mcount + 2 + length;
				  count  = this.in.available();
				}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return resp;
	}
	
	//发送指令
	public boolean sendToReader(byte[] cmd){
		try {
			out.write(cmd);
			out.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		return false;
	}
	
	
	//计算校验和
	public  byte checkSum(byte[] uBuff, int uBuffLen){
		byte crc = 0;
		for(int i = 0; i < uBuffLen; i++){
			crc = (byte) (crc + uBuff[i]);
		}
		crc = (byte) (0xFF&((~crc)+1));
		return crc;
	}

	//判断返回数据是否符合协议
	/**
	 *@return int返回值为0则数据包正确，-1为数据过短，-2包头不正确，-3数据包长度不正确，-4校验码出错
	 *@Method Description:
	 *@Autor Jimmy
	 *@Date 2014-1-11
	 */
	public int isRecvData(byte[] recv){
		if(recv.length <5){
			return -1;//小于最小数据包长度，错误
		}
		String data = Tools.Bytes2HexString(recv, recv.length);
		if(recv[0] != Constants.HEAD) return -2;//数据包包头不正确
		int recvDataLen = Integer.parseInt(data.substring(2, 4), 16);
		if(recvDataLen != recv.length - 2) return -3;//数据包长度不正确
		byte crc = checkSum(recv, recv.length - 1);
		if(crc != recv[recv.length - 1]) return -4;//校验码出错
		return 0;
	}
	@Override
	public void setSensitivity(int value) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void close() {
		// TODO Auto-generated method stub
		
	}
	@Override
	public byte checkSum(byte[] data) {
		// TODO Auto-generated method stub
		return 0;
	}



}
